/**
 * @file boards\gd32f103cb\bsp\bsp_at24cxx.c
 *
 * Copyright (C) 2023
 *
 * bsp_at24cxx.c is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 * @author HinsShum hinsshum@qq.com
 *
 * @encoding utf-8
 */

/*---------- includes ----------*/
#include "at24cxx.h"
#include "gd32f30x_libopt.h"
#include "options.h"


/*---------- macro ----------*/
/*---------- type define ----------*/
/*---------- variable prototype ----------*/
/*---------- function prototype ----------*/
static bool bsp_init(void);
static void bsp_deinit(void);
static void bsp_wp_set(bool enable);
static bool bsp_wp_get(void);
static void bsp_write_cycle_time(void);

/*---------- variable ----------*/
static uint8_t buffer[CONFIG_AT24CXX_BLKSIZE];
static at24cxx_describe_t at24cxx = { .bus_name = "eeioi2c",
                                     .bus = NULL,
                                     .address = 0xA0,
                                     .mem_addr_counts = 2,
                                     .blk_buf = buffer,
                                     .info.start = CONFIG_AT24CXX_BASE,
                                     .info.end = CONFIG_AT24CXX_END,
                                     .info.block_size = CONFIG_AT24CXX_BLKSIZE,
                                     .ops.init = bsp_init,
                                     .ops.deinit = bsp_deinit,
                                     .ops.power = NULL,
                                     .ops.write_protect_set = bsp_wp_set,
                                     .ops.write_protect_get = bsp_wp_get,
                                     .ops.write_cycle_time =
                                         bsp_write_cycle_time,
                                     .ops.cb = NULL,
                                     .ops.on_event = NULL };
DEVICE_DEFINED(at24cxx, at24cxx, &at24cxx);

/*---------- function ----------*/
static bool bsp_init(void) {
  /* GPIO:
   *  WP:    GPIOB2
   *  E_CONT GPIOB1
   */
    rcu_periph_clock_enable(RCU_GPIOB);
    gpio_init(GPIOB, GPIO_MODE_OUT_PP, GPIO_OSPEED_50MHZ,
        GPIO_PIN_1 | GPIO_PIN_2);
/* wirte protect */
    gpio_bit_set(GPIOB, GPIO_PIN_2);
    gpio_bit_reset(GPIOB, GPIO_PIN_1);
    return true;
}

static void bsp_deinit(void) {
    gpio_init(GPIOB, GPIO_MODE_OUT_OD, GPIO_OSPEED_2MHZ, GPIO_PIN_1 | GPIO_PIN_2);
    gpio_bit_set(GPIOB, GPIO_PIN_2);
    gpio_bit_set(GPIOB, GPIO_PIN_1);
}

static void bsp_wp_set(bool enable) {
    if (enable) {
        gpio_bit_set(GPIOB, GPIO_PIN_2);
    }
    else {
        gpio_bit_reset(GPIOB, GPIO_PIN_2);
    }
}

static bool bsp_wp_get(void) {
    return (SET == gpio_output_bit_get(GPIOB, GPIO_PIN_2));
}

static void bsp_write_cycle_time(void) { __delay_ms(6); }
